Dartでenhanced enumsを有効にしてEnumのFactoryを使ってみた
こんにちは、CX事業本部 IoT事業部の若槻です。
最近Flutterアプリ開発でDart言語をよく触っているのですが、今までほぼJS/TS(およびPythonを少々)しか触ってこなかったため、Dartの言語仕様のキャッチアップにヒーヒー言いながら努めています。
今回は、そんなDartを使う中でenhanced enumsを有効にしたEnumsのFactoryを使うことがあったので共有します。
enhanced enumsとは
Dartで使用できるEnumsには、simple enumsとenhanced enumsの2種類があります。
simple enumsは通常のEnumsです。宣言はenum
キーワードを使用して値の列挙を行うだけです。
enum Color { red, green, blue }
一方でenhanced enumsは、次の例のように通常のEnumsに対してクラスのような拡張を行うことが可能です。
enum Vehicle implements Comparable<Vehicle> { car(tires: 4, passengers: 5, carbonPerKilometer: 400), bus(tires: 6, passengers: 50, carbonPerKilometer: 800), bicycle(tires: 2, passengers: 1, carbonPerKilometer: 0); const Vehicle({ required this.tires, required this.passengers, required this.carbonPerKilometer, }); final int tires; final int passengers; final int carbonPerKilometer; int get carbonFootprint => (carbonPerKilometer / passengers).round(); @override int compareTo(Vehicle other) => carbonFootprint - other.carbonFootprint; }
使ってみる
enhanced enumを有効にする
というわけで早速enhanced enumを使おうとしたのですが、Enumsの列挙の末尾に;
を追加するとエラーが発生しました。
enum City { tokyo, osaka, nagoya, other; }
どうやらenhanced enumを有効にするためには、pubspec.yaml
でSDKのバージョンを2.17.0
以上に上げる必要があるようです。
This requires the 'enhanced-enums' language feature to be enabled.
Try updating your pubspec.yaml to set the minimum SDK constraint to 2.17.0 or higher, and running 'pub get'.dart(experiment_not_enabled)
pubspec.yaml
を次のように編集します。
environment: - sdk: ">=2.16.2 <3.0.0" + sdk: ">=2.17.0 <3.0.0"
するとエラーが消えました。有効にできたようです。
Factoryを使ってみる
それではenhanced enumsを使ってEnumsに対してFactoryを実装してみます。
まず、enhanced enumsを下記のようにしてFactoryを作ろうとたのですが、エラーが発生しました。
enum City { tokyo, osaka, nagoya; factory City.fromName(String name) { switch (name) { case '東京': return City.tokyo; case '大阪': return City.osaka; case '名古屋': return City.nagoya; } } }
エラーメッセージによると、null
含めてEnums一覧にない値がreturnされうる記述はだめとのこと。
The body might complete normally, causing 'null' to be returned, but the return type, 'City', is a potentially non-nullable type.
Try adding either a return or a throw statement at the end.dartbody_might_complete_normally
ドキュメントにもそのように記述がありますね。
Factory constructors can only return one of the fixed, known enum instances.
Factoryのcase文を修正し、最終的に下記のようなコードを作りました。
enum City { tokyo, osaka, nagoya, other; factory City.fromName(String name) { switch (name) { case '東京': return City.tokyo; case '大阪': return City.osaka; case '名古屋': return City.nagoya; } return City.other; } } main() { print(City.fromName('東京') == City.tokyo); print(City.fromName('大阪') == City.tokyo); print(City.fromName('名古屋') == City.tokyo); print(City.fromName('出雲') == City.tokyo); }
City.fromName
で引数に応じたCity
の列挙値が取得でき、判定が行えていることが確認できます。
$ dart lib/sample.dart true false false false
おわりに
Dartでenhanced enumsを有効にしてEnumのFactoryを使ってみました。
enhanced enumを使ってひとまずやりたいことが実現できたので良かったです。またドキュメントを見るとFactory以外にも色々できそうなことがあるようなので今後も活用していきたいと思います。
以上